package com.william.jdbcplus.core.conditions.segment;

import com.william.jdbcplus.core.conditions.segment.impl.*;
import com.william.jdbcplus.core.conditions.wrap.JdbcWrap;
import com.william.jdbcplus.core.enums.SqlKeyword;
import com.william.jdbcplus.core.toolkit.StringPool;
import lombok.Getter;

/**
 * 合并 SQL 片段
 *
 * @author NILIWEI
 */
@Getter
public class MergeSegments implements JdbcWrap {
    private final SelectSegmentList selectList = new SelectSegmentList();
    private final FromSegmentList fromList = new FromSegmentList();
    private final WhereSegmentList whereList = new WhereSegmentList();
    private final GroupBySegmentList groupByList = new GroupBySegmentList();
    private final HavingSegmentList havingList = new HavingSegmentList();
    private final OrderBySegmentList orderByList = new OrderBySegmentList();
    private final UnionSegmentList unionList = new UnionSegmentList();
    private final UpdateSegmentList updateList = new UpdateSegmentList();
    private final SetSegmentList setList = new SetSegmentList();
    private final DeleteSegmentList deleteList = new DeleteSegmentList();

    public void setDistinct(boolean distinct) {
        selectList.setDistinct(distinct);
    }

    public void add(SqlKeyword keyword, String segment) {
        if (MatchSegment.SELECT.match(keyword)) {
            selectList.add(segment);
        } else if (MatchSegment.FROM.match(keyword)) {
            fromList.add(segment);
        } else if (MatchSegment.ORDER_BY.match(keyword)) {
            orderByList.add(segment);
        } else if (MatchSegment.GROUP_BY.match(keyword)) {
            groupByList.add(segment);
        } else if (MatchSegment.HAVING.match(keyword)) {
            havingList.add(segment);
        } else if (MatchSegment.UNION.match(keyword)) {
            unionList.add(keyword.toString() + StringPool.SPACE + segment);
        } else if (MatchSegment.UNION_All.match(keyword)) {
            unionList.add(keyword.toString() + StringPool.SPACE + segment);
        } else if (MatchSegment.DELETE.match(keyword)) {
            deleteList.add(segment);
        } else if (MatchSegment.UPDATE.match(keyword)) {
            updateList.add(segment);
        } else if (MatchSegment.SET.match(keyword)) {
            setList.add(segment);
        } else if (MatchSegment.WHERE.match(keyword)) {
            whereList.add(segment);
        }
    }

    public void clear() {
        this.selectList.clear();
        this.fromList.clear();
        this.whereList.clear();
        this.groupByList.clear();
        this.havingList.clear();
        this.orderByList.clear();
        this.unionList.clear();
        this.updateList.clear();
        this.setList.clear();
        this.deleteList.clear();
    }

    public void clearSelect() {
        this.selectList.clear();
    }

    public void clearFrom() {
        this.fromList.clear();
    }

    public void clearWhere() {
        this.whereList.clear();
    }

    public void clearGroupBy() {
        this.groupByList.clear();
    }

    public void clearHaving() {
        this.havingList.clear();
    }

    public void clearOrderBy() {
        this.orderByList.clear();
    }

    public void clearUnion() {
        this.unionList.clear();
    }

    @Override
    public String getSelect() {
        return selectList.getSql();
    }

    @Override
    public String getSelectSegment() {
        return selectList.getSegment();
    }

    @Override
    public String getFrom() {
        return fromList.getSql();
    }

    @Override
    public String getFromSegment() {
        return fromList.getSegment();
    }

    @Override
    public String getWhere() {
        return whereList.getSql();
    }

    @Override
    public String getWhereSegment() {
        return whereList.getSegment();
    }

    @Override
    public String getCountWhere() {
        String sqlSegment = StringPool.EMPTY;
        if (whereList.isEmpty()) {
            if (!groupByList.isEmpty()) {
                sqlSegment = groupByList.getSql() + havingList.getSql();
            }
        } else {
            sqlSegment = whereList.getSql() + groupByList.getSql() + havingList.getSql();
        }
        return sqlSegment;
    }

    /**
     * 获取查询count的where条件， 不带 where
     *
     * @return
     */
    @Override
    public String getCountWhereSegment() {
        String sqlSegment = StringPool.EMPTY;
        if (whereList.isEmpty()) {
            if (!groupByList.isEmpty()) {
                sqlSegment = groupByList.getSql() + havingList.getSql();
            }
        } else {
            sqlSegment = whereList.getSegment() + groupByList.getSql() + havingList.getSql();
        }
        return sqlSegment;
    }

    /**
     * 获取where后面条件， 带 where
     *
     * @return
     */
    public String getWhereBehind() {
        String sql = StringPool.EMPTY;
        if (whereList.isEmpty()) {
            if (!groupByList.isEmpty()) {
                sql = groupByList.getSql() + havingList.getSql() + orderByList.getSql();
            } else {
                sql = orderByList.getSql();
            }
        } else {
            sql = whereList.getSql() + groupByList.getSql() + havingList.getSql() + orderByList.getSql();
        }
        return sql;
    }

    @Override
    public String getGroupBy() {
        return groupByList.getSql();
    }

    @Override
    public String getGroupBySegment() {
        return groupByList.getSegment();
    }

    @Override
    public String getHaving() {
        return havingList.getSql();
    }

    @Override
    public String getHavingSegment() {
        return havingList.getSegment();
    }

    @Override
    public String getOrderBy() {
        return orderByList.getSql();
    }

    @Override
    public String getOrderBySegment() {
        return orderByList.getSegment();
    }

    /**
     * 获取完整查询脚本
     * select sum(table1.id), table1.name
     * from table1 inner join table2 on table1.id = table2.pid
     * where table1.id < 100
     * group by table1.id, table1.name
     * having sum(table1.id) > 10
     * order by sum(table1.id) desc
     *
     * @return
     */
    @Override
    public String getAll() {
        return getQuery();
    }

    /**
     * 获取union查询语句,不可带 order by 条件
     *
     * @return
     */
    public String getUnion() {
        return selectList.getSql() + fromList.getSql() + whereList.getSql()
                + groupByList.getSql() + havingList.getSql() + unionList.getSql();
    }

    /**
     * 获取查询语句
     *
     * @return
     */
    public String getQuery() {
        return selectList.getSql() + fromList.getSql() + whereList.getSql()
                + groupByList.getSql() + havingList.getSql() + orderByList.getSql() + unionList.getSql();
    }

    /**
     * 获取更新语句
     *
     * @return
     */
    public String getUpdate() {
        return updateList.getSql() + setList.getSql() + whereList.getSql();
    }

    /**
     * 获取删除语句
     *
     * @return
     */
    public String getDelete() {
        return deleteList.getSql() + whereList.getSql();
    }

    /**
     * 获取查询条数脚本
     * 1、不含分组查询时
     * --> select count(1) from table where ...
     * 2、包含分组查询时SELECT COUNT(1) FROM ( %s ) TOTAL_
     * --> select count(1) from ( select .. from table where ... group by .. having ... ) as_total_
     *
     * @return
     */
    @Override
    public String getCount() {
        if (groupByList.isEmpty()) {
            return SqlKeyword.SELECT.getSegment() + StringPool.SPACE + SqlKeyword.COUNT_ONE + fromList.getSql()
                    + whereList.getSql() + unionList.getSql();
        } else {
            return SqlKeyword.SELECT.getSegment() + StringPool.SPACE + SqlKeyword.COUNT_ONE + StringPool.SPACE + SqlKeyword.FROM
                    + SqlKeyword.LEFT_BRACKET
                    + selectList.getSql() + fromList.getSql() + whereList.getSql() + groupByList.getSql() + havingList.getSql() + unionList.getSql()
                    + SqlKeyword.RIGHT_BRACKET + " as_total_";
        }
    }
}
